package com.gitee.cliveyuan.tools;

import com.gitee.cliveyuan.tools.enums.DateTimeField;
import com.gitee.cliveyuan.tools.enums.DateTimeFormat;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.util.Date;
import java.util.Objects;

/**
 * 日期时间工具
 *
 * @author: clive
 * Created on 2018/07/23
 * @since: 1.0
 */
public class DateTimeTools {

    private DateTimeTools() {
    }

    /**
     * 当前时间
     */
    public static Date now() {
        return new Date();
    }

    /**
     * 当前本地时间
     */
    public static LocalDateTime nowLocalDateTime() {
        return LocalDateTime.now();
    }

    /**
     * 通过日期生成
     *
     * @param year
     * @param month
     * @param dayOfMonth
     */
    public static Date ofDate(int year, int month, int dayOfMonth) {
        return convertToDate(LocalDateTime.of(year, month, dayOfMonth, 0, 0, 0));
    }

    /**
     * 通过时间生成
     *
     * @param hour
     * @param minute
     * @param second
     */
    public static Date ofTime(int hour, int minute, int second) {
        LocalDateTime localDateTime = nowLocalDateTime();
        return convertToDate(LocalDateTime.of(localDateTime.getYear(),
                localDateTime.getMonth(), localDateTime.getDayOfMonth(),
                hour, minute, second));
    }

    /**
     * 之前
     *
     * @param date1
     * @param date2
     */
    public static boolean before(Date date1, Date date2) {
        Assert.notNull(date1, "date1 can't be null");
        Assert.notNull(date2, "date2 can't be null");
        return date1.before(date2);
    }

    /**
     * 之后
     *
     * @param date1
     * @param date2
     */
    public static boolean after(Date date1, Date date2) {
        Assert.notNull(date1, "date1 can't be null");
        Assert.notNull(date2, "date2 can't be null");
        return date1.after(date2);
    }

    /**
     * 现在之前
     *
     * @param date
     */
    public static boolean beforeNow(Date date) {
        Assert.notNull(date, "date can't be null");
        return before(date, now());
    }

    /**
     * 现在之后
     *
     * @param date
     */
    public static boolean afterNow(Date date) {
        Assert.notNull(date, "date can't be null");
        return after(date, now());
    }

    /**
     * 当前时间格式化
     *
     * @param dateTimeFormat
     */
    public static String format(DateTimeFormat dateTimeFormat) {
        return format(now(), dateTimeFormat);
    }

    /**
     * 日期格式化
     *
     * @param date
     * @param format
     */
    public static String format(Date date, DateTimeFormat format) {
        return format(date, format.getFormat());
    }

    /**
     * 日期格式化
     *
     * @param date
     * @param format
     */
    public static String format(Date date, String format) {
        Assert.notNull(date, "date can't be null");
        Assert.notEmpty(format, "format can't be empty");
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        return simpleDateFormat.format(date);
    }


    /**
     * 日期解析
     *
     * @param dateStr
     * @param format
     * @throws ParseException
     */
    public static Date parse(String dateStr, String format) throws ParseException {
        Assert.notEmpty(dateStr, "dateStr can't be empty");
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        return simpleDateFormat.parse(dateStr);
    }

    /**
     * 日期解析
     *
     * @param dateStr
     * @param format
     * @throws ParseException
     */
    public static Date parse(String dateStr, DateTimeFormat format) throws ParseException {
        return parse(dateStr, format.getFormat());
    }

    /**
     * 日期时间调整
     *
     * @param field 字段
     * @param value 值 (正值增加,负值减少)
     */
    public static Date plus(DateTimeField field, long value) {
        if (Objects.isNull(field)) return null;
        LocalDateTime now = LocalDateTime.now();

        switch (field) {
            case YEAR:
                now = now.plusYears(value);
                break;
            case MONTH:
                now = now.plusMonths(value);
                break;
            case WEEK:
                now = now.plusWeeks(value);
                break;
            case DAY:
                now = now.plusDays(value);
                break;

            case HOUR:
                now = now.plusHours(value);
                break;
            case MINUTE:
                now = now.plusMinutes(value);
                break;
            case SECOND:
                now = now.plusSeconds(value);
                break;
        }
        return convertToDate(now);
    }

    /**
     * 日期转换
     *
     * @param localDateTime
     */
    public static Date convertToDate(LocalDateTime localDateTime) {
        ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zdt = localDateTime.atZone(zoneId);
        return Date.from(zdt.toInstant());
    }

    /**
     * 当前时间的毫秒
     */
    public static long nowMillis() {
        return System.currentTimeMillis();
    }

    /**
     * 计算耗时 单位 毫秒
     *
     * @param startTime
     */
    public static long costTime(long startTime) {
        return nowMillis() - startTime;
    }

    /**
     * 计算耗时 单位:秒
     *
     * @param startTime
     */
    public static int costTimeSecond(long startTime) {
        return (int) (costTime(startTime) / 1000L);
    }


}
